package cis350.pcr;

import cis350.pcr.types.*;
import cis350.pcr.types.Type.RatingType;
import cis350.pcr.types.Type.SearchType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.TreeSet;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;

public class JSONResult {
	public Item result;
	public LinkedHashMap<String, ? extends Item> map;
	public TreeSet<Semester> all_ratings;
	private HashMap<String, String> semester_lookup;

	public JSONResult(ArrayList<String> semester_data, ArrayList<String> semester_label) { 
		this.result = new Item();
		this.map = new LinkedHashMap<String, Item>();
		this.all_ratings = new TreeSet<Semester>();
		this.semester_lookup = new HashMap<String, String>();
		for (int n = 0; n < semester_data.size(); n++){
			semester_lookup.put(semester_label.get(n), semester_data.get(n));
		}
	}
	
	/**
	 * 
	 * @param json_data
	 *            the string of json being sent
	 * @param search_type
	 *            should be either 'course' or 'instructor' or 'dept' (not
	 *            implemented yet)
	 * @return A result that contains all the information from the json
	 */
	public void parse(ArrayList<String> json_data, String description, SearchType search_type,
			String filter) {
		Item temp_result = null;
		LinkedHashMap<String, Item> temp_map = new LinkedHashMap<String, Item>();
		TreeSet<Semester> temp_all_ratings = new TreeSet<Semester>();
		ArrayList<String> rating_types = new ArrayList<String>();
		for (RatingType rt : RatingType.values()){
			rating_types.add(rt.toString());
		}
		try {
			JSONObject json_object = new JSONObject(json_data.get(0));
			JSONObject result = json_object.getJSONObject("result");
			JSONArray values = result.getJSONArray("values");
			JSONObject entry = values.getJSONObject(0);
			JSONObject e_section = entry.getJSONObject("section");
			JSONArray e_aliases = e_section.getJSONArray("aliases");
			switch (search_type) {
			case COURSE:
				temp_result = new Course();
				temp_result.name = Course.rename(e_aliases.get(0).toString());
				((Course) temp_result).title = e_section.getString("name");
				break;
			case INSTRUCTOR: 
				temp_result = new Instructor();
				JSONObject e_instructor = entry.getJSONObject("instructor");
				temp_result.name = e_instructor.getString("name");
				break;
			case COURSE_INSTR:
				temp_result = new Instructor();
				temp_result.name = filter;
				break;
			case INSTR_COURSE:
				temp_result = new Course();
				temp_result.name = filter;
				break;
			case DEPT:
				temp_result = new Department();
				temp_result.name = e_aliases.get(0).toString().split("-")[0];
				search_type = SearchType.INSTRUCTOR;
				break;

			}
			for (int j = 0; j < json_data.size(); j++) {
				json_object = new JSONObject(json_data.get(j));
				result = json_object.getJSONObject("result");
				values = result.getJSONArray("values");
				entry = values.getJSONObject(0);
				e_section = entry.getJSONObject("section");
				
				// loop through entries
				for (int i = 0; i < values.length(); i++) {
					entry = values.getJSONObject(i);

					// update rating info
					Semester temp_semester = new Semester();
					if (!entry.getString("comments").equals("null"))
						temp_semester.comments = entry.getString("comments");
					temp_semester.num_reviewers = entry
							.getString("num_reviewers");
					temp_semester.num_students = entry
							.getString("num_students");
					JSONObject e_rating = entry.getJSONObject("ratings");
					Iterator<String> keys = e_rating.keys();
					for (int n = 0; keys.hasNext(); n++) {
						String rScore = keys.next().toString();
						String score = rScore.replaceFirst("r", "");
						if (rating_types.contains(score)) {
							RatingType temp_type = Enum.valueOf(
									RatingType.class, score);
							temp_semester.scores.put(temp_type,
									Double.valueOf(e_rating.getString(rScore)));
						}
						keys.remove();
					}

					e_section = entry.getJSONObject("section");
					String id = e_section.getString("id").replaceAll("-.*", "");
					temp_semester.id = semester_lookup.get(id);
					if (temp_semester.id == null)
						temp_semester.id = "";
					Item temp_item = null;
					String temp_name = "", temp_filter = "";
					JSONObject e_instructor = null;
					switch (search_type) {
					case COURSE:
						// update instructor
						temp_item = new Instructor();
						e_instructor = entry.getJSONObject("instructor");
						temp_name = e_instructor.getString("name");
						if (temp_map.containsKey(temp_name))
							temp_item = temp_map.get(temp_name);
						else {
							temp_item.name = temp_name;
							((Instructor) temp_item).lastName = getLastName(temp_name);
						}
						break;
					case INSTRUCTOR:
						// update course
						temp_item = new Course();
						e_aliases = e_section.getJSONArray("aliases");
						temp_name = Course.rename(e_aliases.get(0).toString());
						if (temp_map.containsKey(temp_name))
							temp_item = temp_map.get(temp_name);
						else
							temp_item.name = temp_name;
						((Course) temp_item).title = e_section.getString("name");
						break;
					case INSTR_COURSE:
						// update filter
						e_aliases = e_section.getJSONArray("aliases");
						temp_filter = Course.rename(e_aliases.get(0).toString());
						temp_semester.name = temp_semester.id;
						temp_item = temp_semester;
						if (temp_filter.equals(filter))
							((Course) temp_result).title = e_aliases.get(0)
									.toString();
						break;
					case COURSE_INSTR:
						// update filter
						e_instructor = entry.getJSONObject("instructor");
						temp_filter = e_instructor.getString("name");
						temp_semester.name = temp_semester.id;
						temp_item = temp_semester;
						break;
					}

					temp_item.ratings.add(temp_semester);

					// and to map and increment to next value
					Log.v("parse filter", temp_filter + ":" + filter);
					if (temp_filter.equals(filter) || filter.equals("none")) {
						temp_all_ratings.add(temp_semester);
						temp_map.put(temp_item.name, temp_item);
					}
				}
				if (search_type == SearchType.COURSE) {
					((Course) temp_result).description = description;
				}
			}

			this.result = temp_result;
			this.map = temp_map;
			this.all_ratings.addAll(temp_all_ratings);

		} catch (JSONException e) {
			Log.e("json error", e.toString());
		}
		
	}

	private String getLastName(String temp_name) {
		int lastSpace = temp_name.trim().lastIndexOf(" ");
		return temp_name.substring(lastSpace + 1);
	}

}
